package com.neusoft.elmboot.service.impl;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import javax.naming.InsufficientResourcesException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.neusoft.elmboot.mapper.CreditTransactionMapper;
import com.neusoft.elmboot.po.CreditConfig;
import com.neusoft.elmboot.po.CreditTransaction;
import com.neusoft.elmboot.service.CreditTransactionService;

@Service
public class CreditTransactionServiceImpl implements CreditTransactionService {
	
	@Autowired
	private CreditTransactionMapper creditTransactionMapper;

	@Override
	@Transactional
	public int EarnCredits(CreditTransaction creditTransaction) {
		CreditTransactionBo cTransactionBo = new CreditTransactionBo(creditTransaction);
		CreditConfig creditConfig = creditTransactionMapper.getCreditConfig(1);
		BigDecimal increaseRate = creditConfig.getIncreaseRate();
		Integer numOfMonth = 12;
		try {
			cTransactionBo.EarnCredits(increaseRate, numOfMonth);
		} catch (InsufficientResourcesException e) {
			e.printStackTrace();
			return 0;
		}
		
		this.CreditTransactionBo2CreditTransaction(cTransactionBo, creditTransaction);
		
		creditTransactionMapper.saveCreditTransaction(creditTransaction);
		return creditTransaction.getId();
		
	}
	
	private void CreditTransactionBo2CreditTransaction(CreditTransactionBo BO, CreditTransaction CT) {
		CT.setUserId(BO.getUserId());
		CT.setChannalId(BO.getChannalId());
		CT.setEventId(BO.getEventId());
		CT.setCredit(BO.getCredit());
		CT.setCreateTime(BO.getCreateTime());
		CT.setExpiredTime(BO.getExpiredTime());
	}

	@Override
	@Transactional
	public BigDecimal AllCredits(String userId) {
		List<CreditTransaction> creditTransactions = creditTransactionMapper.listCreditTransactionByUserId(userId);
		BigDecimal credits = new BigDecimal(0);
		for(CreditTransaction cTransaction : creditTransactions) {
			credits = credits.add(cTransaction.getCredit());
		}
		return credits;
	}

	@Override
	@Transactional
	public List<com.neusoft.elmboot.po.CreditTransaction> CreditTransaction(String userId) {
		List<CreditTransaction> creditTransactions = creditTransactionMapper.listCreditTransactionByUserId(userId);
		return creditTransactions;
	}

	@Override
	@Transactional
	public List<com.neusoft.elmboot.po.CreditTransaction> EarnCreditTransaction(String userId) {
		List<CreditTransaction> creditTransactions = creditTransactionMapper.listCreditTransactionByUserId(userId);
		List<CreditTransaction> earnCreditTransactions = new ArrayList<CreditTransaction>();
		for(CreditTransaction cTransaction : creditTransactions) {
			if(cTransaction.getCredit().compareTo(BigDecimal.ZERO)>0) {
				earnCreditTransactions.add(cTransaction);
			}
		}
		return earnCreditTransactions;
	}

	@Override
	@Transactional
	public List<com.neusoft.elmboot.po.CreditTransaction> UsedCreditTransaction(String userId) {
		return creditTransactionMapper.listUsedCreditTransactionByUserId(userId);
	}

	@Override
	public int UseCredits(CreditTransaction creditTransaction) {
		CreditTransactionBo cTransactionBo = new CreditTransactionBo(creditTransaction);
		BigDecimal allCredits = this.AllCredits(cTransactionBo.getUserId());
		try {
			cTransactionBo.UseCredits(allCredits);
		} catch (InsufficientResourcesException e) {
			e.printStackTrace();
			return 0;
		}
		this.CreditTransactionBo2CreditTransaction(cTransactionBo, creditTransaction);
		creditTransactionMapper.saveCreditTransaction(creditTransaction);
		return creditTransaction.getId();
		
	}

}

class CreditTransactionBo {
	private String userId;
	private String channalId;
	private String eventId;
	private BigDecimal credit;
	private Timestamp createTime;
	private Timestamp expiredTime;
	
	public CreditTransactionBo(CreditTransaction creditTransaction) {
		this.userId = creditTransaction.getUserId();
		this.channalId = creditTransaction.getChannalId();
		this.eventId = creditTransaction.getEventId();
		this.credit = creditTransaction.getCredit();
		this.createTime = creditTransaction.getCreateTime();
		this.expiredTime = creditTransaction.getExpiredTime();
	}
	
	public void EarnCredits(BigDecimal increaseRate, Integer numOfMonth) throws InsufficientResourcesException {
		if(credit.compareTo(BigDecimal.ZERO)<0) {
			throw new InsufficientResourcesException();
		}
		this.credit = this.credit.add(this.credit.multiply(increaseRate));
		this.createTime = new Timestamp(System.currentTimeMillis());
		this.CreateExpiredTimeByMonth(numOfMonth);
	}
	
	public void UseCredits(BigDecimal allCredits) throws InsufficientResourcesException {
		if(credit.compareTo(BigDecimal.ZERO)<0) {
			throw new InsufficientResourcesException();
		}
		if(credit.compareTo(allCredits)>0) {
			throw new InsufficientResourcesException();
		}
		this.credit = this.credit.negate();
		this.createTime = new Timestamp(System.currentTimeMillis());
		this.CreateExpiredTimeByMonth(0);
	}
	
	private void CreateExpiredTimeByMonth(Integer numOfMonth) {
		// 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        
        // 增加几个月
        LocalDateTime futureDateTime = now.plusMonths(numOfMonth);

        // 转换为时间戳
        this.expiredTime = Timestamp.valueOf(futureDateTime);
	}
	
	
	public String getUserId() {
		return userId;
	}
	public void setUserId(String userId) {
		this.userId = userId;
	}
	public String getChannalId() {
		return channalId;
	}
	public void setChannalId(String channalId) {
		this.channalId = channalId;
	}
	public String getEventId() {
		return eventId;
	}
	public void setEventId(String eventId) {
		this.eventId = eventId;
	}
	public BigDecimal getCredit() {
		return credit;
	}
	public void setCredit(BigDecimal credit) {
		this.credit = credit;
	}
	public Timestamp getCreateTime() {
		return createTime;
	}
	public void setCreateTime(Timestamp createTime) {
		this.createTime = createTime;
	}
	public Timestamp getExpiredTime() {
		return expiredTime;
	}
	public void setExpiredTime(Timestamp expiredTime) {
		this.expiredTime = expiredTime;
	}
}
